#include "printk.h"
void do_divide_error(unsigned long rsp, unsigned long error_code)
{
    unsigned long *p = NULL;
    //rsp指向当前栈顶，即r15，向上索引0x98可以获得rip寄存器值，并将其作为产生异常指令的地址值
    p = (unsigned long *)(rsp + 0x98);
    color_printk(RED, BLACK, "do_divide_error(0), ERRCODE:%#0181x,RSP:%#0181x,RIP:%#0181x\n", error_code, rsp, *p);
    while (1)
        ;
}

void do_nmi(unsigned long rsp, unsigned long error_code)
{
    unsigned long *p = NULL;
    //rsp指向当前栈顶，即r15，向上索引0x98可以获得rip寄存器值，并将其作为产生异常指令的地址值
    p = (unsigned long *)(rsp + 0x98);
    color_printk(RED, BLACK, "do_nmi(2), ERRCODE:%#0181x,RSP:%#0181x,RIP:%#0181x\n", error_code, rsp, *p);
    while (1)
        ;
}

void do_invalid_TTS(unsigned long rsp, unsigned long error_code)
{
    unsigned long *p = NULL;
    //rsp指向当前栈顶，即r15，向上索引0x98可以获得rip寄存器值，并将其作为产生异常指令的地址值
    p = (unsigned long *)(rsp + 0x98);
    color_printk(RED, BLACK, "do_invalid_TTS(10), ERRCODE:%#0181x,RSP:%#0181x,RIP:%#0181x\n", error_code, rsp, *p);
    if (error_code & 0x01)
        color_printk(RED, BLACK, "The exception occurred during delivery of an event external"
                                 " to the program");
    if (error_code & 0x02)
        color_printk(RED, BLACK, "Refers to a gate descriptor in the IDT;\n");
    else
        color_printk(RED, BLACK, "Refers to a descriptor in the GDT or the current LDT;\n");
    if ((error_code & 0x02) == 0)
        if (error_code & 0x04)
            color_printk(RED, BLACK, "Refers to a segment or gate descriptor in the LDT;\n");
        else
            color_printk(RED, BLACK, "Refers to a descriptor in the current GDT;\n");
    color_printk(RED, BLACK, "Segment Selector Index:%#010x\n", error_code & 0xfff8);
}

/*
处理器为页错误异常提供了两条信息，来帮助诊断异常产生的原因以及恢复方法
1.栈中错误码
2.cr2控制寄存器
在异常触发时，处理器会将cs和eip寄存器保存到异常处理程序栈中，通常情况下这两个寄存器值指向触发异常的指令
*/

void do_page_fault(unsigned long rsp, unsigned long error_code)
{
    unsigned long *p = NULL;
    //将cr2寄存器的值存储在栈中
    unsigned long cr2 = 0;
    __asm__ __volatile__("movq	%%cr2,	%0"
                         : "=r"(cr2)::"memory");
    p = (unsigned long *)(rsp + 0x98);

    color_printk(RED, BLACK, "do_page_fault(14),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n", error_code, rsp, *p);

    if (!(error_code & 0x01))
        color_printk(RED, BLACK, "Page Not-Present,\t");

    if (error_code & 0x02)
        color_printk(RED, BLACK, "Write Cause Fault,\t");
    else
        color_printk(RED, BLACK, "Read Cause Fault,\t");

    if (error_code & 0x04)
        color_printk(RED, BLACK, "Fault in user(3)\t");
    else
        color_printk(RED, BLACK, "Fault in supervisor(0,1,2)\t");

    if (error_code & 0x08)
        color_printk(RED, BLACK, ",Reserved Bit Cause Fault\t");

    if (error_code & 0x10)
        color_printk(RED, BLACK, ",Instruction fetch Cause Fault");

    color_printk(RED, BLACK, "\n");

    color_printk(RED, BLACK, "CR2:%#018lx\n", cr2);

    while (1)
        ;
}